{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 6.1 最优化理论和深度学习\n",
    "最优化理论是计算机科学中一个重要的概念，它用于帮助我们找到最优解（即最小或最大值）的算法。在深度学习中，最优化理论用于帮助深度学习模型找到最优解。深度学习模型常常有数百万甚至上亿个参数，如果使用暴力枚举的方法来寻找最优解，时间成本将非常高。最优化理论提供了一系列的最优化算法，如随机梯度下降（SGD）、动量法、RMSProp 和 Adam，用于帮助我们快速找到最优解。\n",
    "\n",
    "尽管密切联系，但二者毕竟不是一回事，因此，先让我们来看看它们之间的不同。\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 6.1.1 最优化和深度学习的差异\n",
    "\n",
    "最优化和深度学习之间的不同点在于：\n",
    "\n",
    "1. 目标不同：最优化的目标是找到使得某个目标函数取得最优解的参数，而深度学习的目标则是通过调整模型的参数来最小化损失函数，使模型在新数据上的表现尽可能地好。换句话说，前者关注的训练误差最小，而后者关注的是泛化误差最小。\n",
    "\n",
    "2. 应用领域不同：最优化是一种通用的工具，可以应用于各种领域。而深度学习是一种特定的机器学习技术，常常用于解决图像识别、语音识别、自然语言处理等问题。\n",
    "\n",
    "3. 实现方式不同：最优化是一种算法，通常用数学形式来表示。而深度学习则是一种机器学习框架，常常使用深度学习框架如 PyTorch、TensorFlow 等来实现。\n",
    "\n",
    "4. 研究内容不同：最优化研究的是如何找到最优解的算法，而深度学习研究的是如何使用多层神经网络来解决特定问题的方法。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 6.1.2 训练误差和泛化误差\n",
    "\n",
    "刚才我们提到关注训练误差和泛化误差是最优化和深度学习之间一个比较大的差异。这其实还涉及到机器学习中“风险”的概念，有必要区分一下。\n",
    "\n",
    "在机器学习中，训练误差、泛化误差、经验风险、风险这几个概念之间有着密切的关系。它们之间的区别如下：\n",
    "\n",
    "1. 训练误差（Training Error）：指模型在训练数据上的误差，即使用训练数据计算的损失函数的值。\n",
    "2. 泛化误差（Generalization Error）：指模型在新数据上的误差，即使用测试数据计算的损失函数的值。\n",
    "3. 经验风险（Empirical Risk）：指使用训练数据计算的损失函数的值，你可以简单认为这就是训练误差的不同说法而已。\n",
    "4. 风险（Risk）：指使用真实数据计算的损失函数的期望值。\n",
    "\n",
    "通常，深度学习中希望模型的泛化误差尽可能小，但由于我们无法直接计算真实的风险，因此只能通过训练数据估计经验风险，并希望通过优化经验风险来最小化泛化误差。在训练过程中，如果训练误差很小而泛化误差很大，则说明模型存在过拟合的问题，即模型过于复杂，无法很好地泛化到新的数据。因此，我们需要使用正则化技术来减小过拟合的风险。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 6.1.3 最优化算法的主要问题及对策\n",
    "\n",
    "本章咱们关注的是深度学习中的最优化算法，而不是如何解决深度学习中的泛化误差问题。这方面的内容我们在上一章已经讲过一些，比如过拟合、欠拟合问题等，可以用正则化技术，增加训练数据、减小模型复杂度等办法解决。\n",
    "\n",
    "在机器学习中，优化算法的主要问题包括：\n",
    "\n",
    "#### 1. 局部最小值（Local Minimum）\n",
    "如下图所示，局部最小值指在某个局部区域内，目标函数的值小于周围所有点的值。局部最小值可能是全局最小值，也可能不是。局部最小值是机器学习模型训练中常见的问题。\n",
    "\n",
    "<img src=\"../images/6-1-1.png\" width=\"50%\"></img>\n",
    "\n",
    "\n",
    "举例来说，在梯度下降算法中，我们需要不断迭代调整模型参数来使损失函数的值不断减小。然而，如果我们的模型存在局部最小值，则损失函数的值可能在某个点处停止减小，即使我们继续迭代也不会得到更优的结果。\n",
    "\n",
    "为了解决这个问题，我们可以使用不同的优化算法，例如随机梯度下降算法或 Adam 算法。这些算法在每次迭代时使用随机的梯度来调整模型参数，从而避免局部最小值的出现。\n",
    "\n",
    "另外，我们也可以使用训练数据的不同子集来训练模型，从而避免局部最小值的出现。\n",
    "\n",
    "#### 2. 鞍点（Saddle Point）\n",
    "\n",
    "<img src=\"../images/6-1-2.png\" alt=\"From wikipedia\" width=\"50%\"></img>\n",
    "\n",
    "如图所示，鞍点（saddle point）是指在机器学习模型训练过程中，损失函数在某一点取得最小值或最大值，但是这个点不是全局最优解。\n",
    "\n",
    "鞍点是一种特殊的局部最小值，它在机器学习模型训练过程中也是常见的问题。当模型遇到鞍点时，损失函数的值可能不再减小或不再增大，即使继续训练模型也不会得到更优的结果。\n",
    "\n",
    "鞍点常常是由于模型的复杂度过高或者训练样本数量过少造成的。例如，如果模型的复杂度过高，则模型可能会在训练数据集上表现得非常优秀，但是在测试数据集上表现得很差，因为模型过度拟合训练数据。\n",
    "\n",
    "为了解决鞍点问题，我们可以使用不同的优化算法，例如随机梯度下降算法或 Adam 算法。这些算法在每次迭代时使用随机的梯度来调整模型参数，从而避免鞍点的出现。解决鞍点问题的其他方法还包括：\n",
    "\n",
    "1) 减少模型的复杂度：通过减少模型中参数的数量或者使用正则化技术来降低模型的复杂度。这可以减少模型对训练数据的依赖，从而避免鞍点的出现。\n",
    "\n",
    "2) 使用更多的训练数据：通过增加训练数据的数量来降低模型对训练数据的依赖，从而避免鞍点的出现。\n",
    "\n",
    "3) 使用随机初始化：在训练模型之前，我们可以使用随机初始化技术来随机初始化模型参数。这可以避免模型被限制在某一个区域，从而避免鞍点的出现。\n",
    "\n",
    "4) 使用更多的超参数搜索：超参数是指在训练模型之前需要人为设定的参数。我们可以使用超参数搜索技术来自动调整超参数的值，从而找到最优的模型设置。超参数搜索可以帮助我们找到较优的模型设置，从而避免鞍点的出现。\n",
    "\n",
    "5) 使用分类器集成：分类器集成是指将多个分类器结合起来，通过投票或加权平均等方式得到最终的预测结果。分类器集成可以帮助我们减少单个分类器的偏差，从而避免鞍点的出现。\n",
    "\n",
    "#### 3. 梯度消失（Gradient Vanishing）\n",
    "梯度消失是指在机器学习模型训练过程中，由于梯度太小而无法有效地更新模型参数的现象。这通常出现在使用深度神经网络时。它出现的原因是，在深度神经网络中，每一层的输出都会传递到下一层，而这些输出通常都是小于1的数。因此，当输入在多层神经网络中经过多次计算后，其输出会越来越小，从而导致梯度变得越来越小。如图所示，sigmoid函数和它的导数，可以看到x>4时，梯度就基本上为零了。\n",
    "\n",
    "<img src=\"../images/6-1-3.webp\"  width=\"50%\"></img>\n",
    "\n",
    "梯度消失会导致模型训练效果差，甚至无法训练。因此，我们需要采取一些措施来避免梯度消失的出现。解决梯度消失的方法包括：\n",
    "\n",
    "1) 更小的学习率：减小学习率可以减少梯度变化的幅度，从而避免梯度消失的出现。\n",
    "\n",
    "2) 激活函数：使用激活函数，如 ReLU 函数，可以有效地缓解梯度消失问题。\n",
    "\n",
    "3) 残差网络：残差网络可以通过跳过一些层来缓解梯度消失的问题。\n",
    "\n",
    "4) 批标准化：批标准化可以通过在每一层之前对输入数据进行标准化来缓解梯度消失的问题。\n",
    "\n",
    "5) 梯度弥散：梯度弥散是指在每一层之前将输入数据乘上一个小于 1 的数，从而缓解梯度消失的问题。\n",
    "\n",
    "#### 4. 梯度爆炸（Gradient Explosion）\n",
    "梯度爆炸是指在机器学习模型训练过程中，由于梯度过大而导致模型参数更新过快，使得模型训练效果变差的现象。这通常出现在使用深度神经网络时。\n",
    "\n",
    "梯度爆炸的原因是，在深度神经网络中，每一层的输出都会传递到下一层，而这些输出通常都是小于 1 的数。因此，当输入在多层神经网络中经过多次计算后，其输出会越来越小，从而导致梯度变得越来越小。但是，如果使用的激活函数对输入的影响过大，则梯度可能会变得越来越大，从而导致梯度爆炸的出现。例如，使用 sigmoid 函数作为激活函数时，当输入接近 0 或 1 时，梯度会变得非常小。但是，当输入接近 0 或 1 时，sigmoid 函数的导数会变得非常大，从而导致梯度爆炸的出现。\n",
    "\n",
    "梯度爆炸会导致模型训练效果差，甚至无法训练。因此，我们需要采取一些措施来避免梯度爆炸的出现。例如：\n",
    "\n",
    "1) 更大的学习率：增大学习率可以增加梯度变化的幅度，从而避免梯度爆炸的出现。但是，过大的学习率也会导致模型训练效果变差，因此需要调整学习率的大小。\n",
    "\n",
    "2) 更多的数据：使用更多的训练数据可以减少模型的泛化误差，从而避免梯度爆炸的出现。但是，使用更多的数据也会增加训练时间，因此需要考虑数据的数量和训练时间的平衡。\n",
    "\n",
    "3) 更小的隐藏单元数：使用更少的隐藏单元可以减少模型的复杂度，从而避免梯度爆炸的出现。但是，使用更少的隐藏单元也会导致模型的泛化能力下降，因此需要考虑隐藏单元数量和模型泛化能力的平衡。\n",
    "\n",
    "4) 使用正则化：使用正则化可以限制模型的复杂度，从而避免梯度爆炸的出现。正则化有多种方式，例如 L1 正则化、L2 正则化和 Dropout 等。\n",
    "\n",
    "5) 使用残差网络：残差网络可以通过在每一层之间加入残差连接来减少梯度消失和梯度爆炸的问题。残差连接可以使每一层的输出与输入之间相加，从而减少梯度消失和梯度爆炸的问题。\n",
    "\n",
    "#### 解决办法\n",
    "这四个问题都会导致优化算法无法找到最优解。因此，需要使用一些技术来解决这些问题，例如使用 Adam 优化算法、使用 Batch Normalization 等。这就是本章各种梯度下降算法及其变体研究的内容了。咱们一个个来讨论。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**梗直哥提示：本章介绍的内容主要是最优化算法的问题及其解决方案，这和深度学习算法既密切联系，又有所区别，要注意体会其中的异同，知道哪些问题是属于哪个范畴的，要不特别容易弄混乱了。**"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "[Next 6-2 损失函数性质](./6-2%20损失函数性质.ipynb)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.8.10"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
